package net.jcip.chapter4;

import net.jcip.annotations.*;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Counter
 * <p/>
 * Simple thread-safe counter using the Java monitor pattern
 *
 * @author Brian Goetz and Tim Peierls
 */
@ThreadSafe
final class Counter {
    @GuardedBy("this")
    private long value = 0;


    private synchronized long getValue() {
        return value;
    }

    private synchronized long increment() {
        if (value == Long.MAX_VALUE)
            throw new IllegalStateException("counter overflow");
        return value++;
    }


    private long notSafeValue = 0;


    private long getNotSafeValue() {
        return notSafeValue;
    }

    private long notSafeIncrement() {
        if (value == Long.MAX_VALUE)
            throw new IllegalStateException("counter overflow");
        return ++notSafeValue;
    }


    private final static Integer THREAD_NUM = 100;


    /**
     * executorService 仅仅靠自身无法  实现 线程 join  ;
     * CountDownLatch能够使 一个线程  在等待另外 多个线程  完成各自工作之后，再继续执行
     * 就像 t 病毒 + Plagas 寄生虫 一样 组合成为 强大的武器
     */
    public static void main(String[] args) throws InterruptedException {

        Counter counter = new Counter();


        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_NUM);
        CountDownLatch latch = new CountDownLatch(THREAD_NUM);
        for (int i = 0; i < THREAD_NUM; i++) {

            executorService.execute(
                    () -> {
                        for (int j = 0; j < 1000; j++) {
                            counter.notSafeIncrement();
                        }
                        latch.countDown();
                    }
            );
        }

        //  executorService.awaitTermination(2,  TimeUnit.SECONDS);
        latch.await(10, TimeUnit.SECONDS );
        executorService.shutdown();  //shutdown()：停止接收新任务，原来的任务继续执行

        System.out.println("ERROR  counter.notSafeValue ==> " + counter.getNotSafeValue());

        ExecutorService executorService1 = Executors.newFixedThreadPool(THREAD_NUM);
        CountDownLatch latch1 = new CountDownLatch(THREAD_NUM);
        for (int i = 0; i < THREAD_NUM; i++) {

            executorService1.execute(
                    () -> {
                        for (int j = 0; j < 1000; j++) {
                            counter.increment();
                        }
                        latch1.countDown();
                    }
            );
        }


        latch1.await(10, TimeUnit.SECONDS );


        //executorService1.awaitTermination(2,  TimeUnit.SECONDS);


        executorService1.shutdown();

        // Thread.sleep(1000);
        System.out.println("INFO counter.safeValue ==> " + counter.getValue());


    }


}
